"""
简化的摄像头服务
Simplified Camera Service

提供摄像头管理的核心功能：
- 摄像头CRUD操作
- 基本的数据验证
- WVP设备集成
- 简化的状态管理
- 数据库集成
"""
import logging
import json
from typing import List, Optional, Dict, Any, Tuple
from datetime import datetime
from dataclasses import dataclass
from enum import Enum

from config.settings import settings
from database.simple_db import get_database_manager

logger = logging.getLogger(__name__)


class CameraStatus(str, Enum):
    """摄像头状态枚举"""
    ONLINE = "online"
    OFFLINE = "offline"
    ERROR = "error"
    MAINTENANCE = "maintenance"


class StreamStatus(str, Enum):
    """流状态枚举"""
    INACTIVE = "inactive"
    ACTIVE = "active"
    ERROR = "error"
    RECONNECTING = "reconnecting"


@dataclass
class CameraInfo:
    """摄像头信息数据类"""
    id: Optional[int] = None
    name: str = ""
    longitude: float = 0.0
    latitude: float = 0.0
    height: float = 10.0
    location: Optional[str] = None
    rtsp_url: Optional[str] = None
    wvp_device_id: Optional[str] = None
    wvp_channel_id: Optional[str] = None
    description: Optional[str] = None
    ai_enabled: bool = False
    status: CameraStatus = CameraStatus.OFFLINE
    stream_status: StreamStatus = StreamStatus.INACTIVE
    ai_algorithms: Optional[Dict[str, Any]] = None
    processing_fps: int = 3
    priority_level: int = 5
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
    last_frame_time: Optional[datetime] = None
    reconnect_count: int = 0
    last_error: Optional[str] = None


@dataclass
class CameraFilters:
    """摄像头筛选条件"""
    name: Optional[str] = None
    location: Optional[str] = None
    status: Optional[CameraStatus] = None
    ai_enabled: Optional[bool] = None
    wvp_device_id: Optional[str] = None
    page: int = 1
    size: int = 10


class CameraService:
    """简化的摄像头服务"""
    
    def __init__(self):
        # 数据库管理器
        self.db = get_database_manager()
        
        # 缓存（可选，用于提高性能）
        self._cache_enabled = True
        self._cache: Dict[int, CameraInfo] = {}
        self._cache_timeout = 300  # 5分钟缓存
    
    def _dict_to_camera_info(self, camera_dict: Dict[str, Any]) -> CameraInfo:
        """将数据库字典转换为CameraInfo对象"""
        if not camera_dict:
            return None
        
        # 解析AI算法JSON
        ai_algorithms = None
        if camera_dict.get('ai_algorithms'):
            try:
                ai_algorithms = json.loads(camera_dict['ai_algorithms'])
            except (json.JSONDecodeError, TypeError):
                ai_algorithms = None
        
        # 解析时间戳
        created_at = None
        updated_at = None
        last_frame_time = None
        
        if camera_dict.get('created_at'):
            try:
                created_at = datetime.fromisoformat(camera_dict['created_at'].replace('Z', '+00:00'))
            except:
                created_at = None
        
        if camera_dict.get('updated_at'):
            try:
                updated_at = datetime.fromisoformat(camera_dict['updated_at'].replace('Z', '+00:00'))
            except:
                updated_at = None
        
        if camera_dict.get('last_frame_time'):
            try:
                last_frame_time = datetime.fromisoformat(camera_dict['last_frame_time'].replace('Z', '+00:00'))
            except:
                last_frame_time = None
        
        return CameraInfo(
            id=camera_dict.get('id'),
            name=camera_dict.get('name', ''),
            longitude=camera_dict.get('longitude', 0.0),
            latitude=camera_dict.get('latitude', 0.0),
            height=camera_dict.get('height', 10.0),
            location=camera_dict.get('location'),
            rtsp_url=camera_dict.get('rtsp_url'),
            wvp_device_id=camera_dict.get('wvp_device_id'),
            wvp_channel_id=camera_dict.get('wvp_channel_id'),
            description=camera_dict.get('description'),
            ai_enabled=bool(camera_dict.get('ai_enabled', False)),
            status=CameraStatus(camera_dict.get('status', 'offline')),
            stream_status=StreamStatus(camera_dict.get('stream_status', 'inactive')),
            ai_algorithms=ai_algorithms,
            processing_fps=camera_dict.get('processing_fps', 3),
            priority_level=camera_dict.get('priority_level', 5),
            created_at=created_at,
            updated_at=updated_at,
            last_frame_time=last_frame_time,
            reconnect_count=camera_dict.get('reconnect_count', 0),
            last_error=camera_dict.get('last_error')
        )
    
    def create_camera(self, camera_data: Dict[str, Any]) -> CameraInfo:
        """创建摄像头"""
        try:
            # 基本验证
            if not camera_data.get("name"):
                raise ValueError("摄像头名称不能为空")
            
            name = camera_data["name"].strip()
            
            # 检查名称是否已存在
            existing = self.db.get_camera_by_name(name)
            if existing:
                raise ValueError(f"摄像头名称 '{name}' 已存在")
            
            # 验证坐标
            longitude = camera_data.get("longitude", 0.0)
            latitude = camera_data.get("latitude", 0.0)
            if not (-180 <= longitude <= 180):
                raise ValueError("经度必须在 -180 到 180 之间")
            if not (-90 <= latitude <= 90):
                raise ValueError("纬度必须在 -90 到 90 之间")
            
            # 创建摄像头记录
            camera_id = self.db.create_camera(camera_data)
            
            # 从数据库获取完整信息
            camera_dict = self.db.get_camera_by_id(camera_id)
            camera = self._dict_to_camera_info(camera_dict)
            
            # 更新缓存
            if self._cache_enabled:
                self._cache[camera.id] = camera
            
            logger.info(f"摄像头创建成功: {camera.name} (ID: {camera.id})")
            return camera
            
        except Exception as e:
            logger.error(f"创建摄像头失败: {e}")
            raise
    
    def get_camera_by_id(self, camera_id: int) -> Optional[CameraInfo]:
        """根据ID获取摄像头"""
        try:
            # 先检查缓存
            if self._cache_enabled and camera_id in self._cache:
                return self._cache[camera_id]
            
            # 从数据库获取
            camera_dict = self.db.get_camera_by_id(camera_id)
            if not camera_dict:
                return None
            
            camera = self._dict_to_camera_info(camera_dict)
            
            # 更新缓存
            if self._cache_enabled:
                self._cache[camera_id] = camera
            
            return camera
            
        except Exception as e:
            logger.error(f"获取摄像头失败: {e}")
            return None
    
    def get_camera_by_name(self, name: str) -> Optional[CameraInfo]:
        """根据名称获取摄像头"""
        try:
            camera_dict = self.db.get_camera_by_name(name)
            if not camera_dict:
                return None
            
            camera = self._dict_to_camera_info(camera_dict)
            
            # 更新缓存
            if self._cache_enabled:
                self._cache[camera.id] = camera
            
            return camera
            
        except Exception as e:
            logger.error(f"根据名称获取摄像头失败: {e}")
            return None
    
    def get_camera_by_wvp_device(self, device_id: str, channel_id: Optional[str] = None) -> Optional[CameraInfo]:
        """根据WVP设备ID获取摄像头"""
        try:
            camera_dict = self.db.get_camera_by_wvp_device(device_id, channel_id)
            if not camera_dict:
                return None
            
            camera = self._dict_to_camera_info(camera_dict)
            
            # 更新缓存
            if self._cache_enabled:
                self._cache[camera.id] = camera
            
            return camera
            
        except Exception as e:
            logger.error(f"根据WVP设备获取摄像头失败: {e}")
            return None
    
    def update_camera(self, camera_id: int, update_data: Dict[str, Any]) -> Optional[CameraInfo]:
        """更新摄像头信息"""
        try:
            # 检查摄像头是否存在
            existing = self.db.get_camera_by_id(camera_id)
            if not existing:
                logger.warning(f"摄像头不存在: {camera_id}")
                return None
            
            # 检查名称冲突
            if "name" in update_data:
                new_name = update_data["name"].strip()
                if new_name != existing['name']:
                    name_conflict = self.db.get_camera_by_name(new_name)
                    if name_conflict and name_conflict['id'] != camera_id:
                        raise ValueError(f"摄像头名称 '{new_name}' 已存在")
            
            # 执行更新
            success = self.db.update_camera(camera_id, update_data)
            if not success:
                return None
            
            # 获取更新后的数据
            camera_dict = self.db.get_camera_by_id(camera_id)
            camera = self._dict_to_camera_info(camera_dict)
            
            # 更新缓存
            if self._cache_enabled:
                self._cache[camera_id] = camera
            
            logger.info(f"摄像头更新成功: {camera.name} (ID: {camera_id})")
            return camera
            
        except Exception as e:
            logger.error(f"更新摄像头失败: {e}")
            raise
    
    def delete_camera(self, camera_id: int) -> bool:
        """删除摄像头"""
        try:
            # 检查摄像头是否存在
            existing = self.db.get_camera_by_id(camera_id)
            if not existing:
                logger.warning(f"摄像头不存在: {camera_id}")
                return False
            
            # 执行删除
            success = self.db.delete_camera(camera_id)
            
            if success:
                # 从缓存中删除
                if self._cache_enabled and camera_id in self._cache:
                    del self._cache[camera_id]
                
                logger.info(f"摄像头删除成功: {existing['name']} (ID: {camera_id})")
            
            return success
            
        except Exception as e:
            logger.error(f"删除摄像头失败: {e}")
            return False
    
    def get_camera_list(self, filters: CameraFilters) -> Tuple[List[CameraInfo], int]:
        """获取摄像头列表"""
        try:
            # 构建筛选条件
            filter_dict = {}
            if filters.name:
                filter_dict['name'] = filters.name
            if filters.location:
                filter_dict['location'] = filters.location
            if filters.status:
                filter_dict['status'] = filters.status.value
            if filters.ai_enabled is not None:
                filter_dict['ai_enabled'] = filters.ai_enabled
            if filters.wvp_device_id:
                filter_dict['wvp_device_id'] = filters.wvp_device_id
            
            # 从数据库获取数据
            camera_dicts, total = self.db.get_camera_list(filter_dict, filters.page, filters.size)
            
            # 转换为CameraInfo对象
            cameras = [self._dict_to_camera_info(camera_dict) for camera_dict in camera_dicts]
            
            logger.debug(f"获取摄像头列表: 总数={total}, 返回={len(cameras)}")
            return cameras, total
            
        except Exception as e:
            logger.error(f"获取摄像头列表失败: {e}")
            return [], 0
    
    def update_camera_status(self, camera_id: int, status: CameraStatus) -> bool:
        """更新摄像头状态"""
        try:
            update_data = {'status': status.value}
            success = self.db.update_camera(camera_id, update_data)
            
            if success:
                # 更新缓存
                if self._cache_enabled and camera_id in self._cache:
                    self._cache[camera_id].status = status
                    self._cache[camera_id].updated_at = datetime.now()
                
                logger.info(f"摄像头状态更新成功: ID={camera_id} -> {status}")
            
            return success
            
        except Exception as e:
            logger.error(f"更新摄像头状态失败: {e}")
            return False
    
    def update_stream_status(self, camera_id: int, stream_status: StreamStatus, 
                           last_frame_time: Optional[datetime] = None) -> bool:
        """更新流状态"""
        try:
            update_data = {'stream_status': stream_status.value}
            if last_frame_time:
                update_data['last_frame_time'] = last_frame_time.isoformat()
            
            success = self.db.update_camera(camera_id, update_data)
            
            if success:
                # 更新缓存
                if self._cache_enabled and camera_id in self._cache:
                    self._cache[camera_id].stream_status = stream_status
                    if last_frame_time:
                        self._cache[camera_id].last_frame_time = last_frame_time
                    self._cache[camera_id].updated_at = datetime.now()
                
                logger.debug(f"摄像头流状态更新成功: ID={camera_id} -> {stream_status}")
            
            return success
            
        except Exception as e:
            logger.error(f"更新摄像头流状态失败: {e}")
            return False
    
    def get_online_cameras(self) -> List[CameraInfo]:
        """获取在线摄像头列表"""
        try:
            camera_dicts = self.db.get_cameras_by_status('online')
            return [self._dict_to_camera_info(camera_dict) for camera_dict in camera_dicts]
        except Exception as e:
            logger.error(f"获取在线摄像头失败: {e}")
            return []
    
    def get_ai_enabled_cameras(self, status_filter: Optional[CameraStatus] = None) -> List[CameraInfo]:
        """获取启用AI的摄像头列表"""
        try:
            status_value = status_filter.value if status_filter else None
            camera_dicts = self.db.get_ai_enabled_cameras(status_value)
            return [self._dict_to_camera_info(camera_dict) for camera_dict in camera_dicts]
        except Exception as e:
            logger.error(f"获取AI启用摄像头失败: {e}")
            return []
    
    def get_cameras_by_location(self, location: str, exact_match: bool = False) -> List[CameraInfo]:
        """根据位置获取摄像头列表"""
        try:
            # 使用数据库的模糊查询功能
            filter_dict = {'location': location}
            camera_dicts, _ = self.db.get_camera_list(filter_dict, 1, 1000)  # 获取所有匹配的
            
            cameras = [self._dict_to_camera_info(camera_dict) for camera_dict in camera_dicts]
            
            if exact_match:
                cameras = [camera for camera in cameras if camera.location == location]
            
            return cameras
        except Exception as e:
            logger.error(f"根据位置获取摄像头失败: {e}")
            return []
    
    def get_cameras_by_coordinates(self, min_lng: float, max_lng: float, 
                                  min_lat: float, max_lat: float) -> List[CameraInfo]:
        """根据坐标范围获取摄像头列表"""
        try:
            # 获取所有摄像头，然后在内存中筛选（简化实现）
            camera_dicts, _ = self.db.get_camera_list({}, 1, 10000)
            cameras = [self._dict_to_camera_info(camera_dict) for camera_dict in camera_dicts]
            
            # 筛选坐标范围
            filtered_cameras = [
                camera for camera in cameras
                if min_lng <= camera.longitude <= max_lng and min_lat <= camera.latitude <= max_lat
            ]
            
            return filtered_cameras
        except Exception as e:
            logger.error(f"根据坐标范围获取摄像头失败: {e}")
            return []
    
    def batch_update_status(self, camera_ids: List[int], status: CameraStatus) -> int:
        """批量更新摄像头状态"""
        try:
            updated_count = self.db.batch_update_status(camera_ids, status.value)
            
            # 更新缓存
            if self._cache_enabled:
                for camera_id in camera_ids:
                    if camera_id in self._cache:
                        self._cache[camera_id].status = status
                        self._cache[camera_id].updated_at = datetime.now()
            
            logger.info(f"批量更新状态完成: {updated_count}/{len(camera_ids)} 成功")
            return updated_count
        except Exception as e:
            logger.error(f"批量更新状态失败: {e}")
            return 0
    
    def batch_update_ai_enabled(self, camera_ids: List[int], ai_enabled: bool) -> int:
        """批量更新AI启用状态"""
        try:
            updated_count = 0
            
            for camera_id in camera_ids:
                update_data = {'ai_enabled': ai_enabled}
                if self.db.update_camera(camera_id, update_data):
                    updated_count += 1
                    
                    # 更新缓存
                    if self._cache_enabled and camera_id in self._cache:
                        self._cache[camera_id].ai_enabled = ai_enabled
                        self._cache[camera_id].updated_at = datetime.now()
            
            logger.info(f"批量更新AI状态完成: {updated_count}/{len(camera_ids)} 成功")
            return updated_count
        except Exception as e:
            logger.error(f"批量更新AI状态失败: {e}")
            return 0
    
    def get_statistics(self) -> Dict[str, Any]:
        """获取统计信息"""
        try:
            stats = self.db.get_statistics()
            
            # 计算比率
            total = stats.get('total', 0)
            if total > 0:
                stats['online_rate'] = round(stats.get('online', 0) / total * 100, 2)
                stats['ai_enabled_rate'] = round(stats.get('ai_enabled', 0) / total * 100, 2)
            else:
                stats['online_rate'] = 0.0
                stats['ai_enabled_rate'] = 0.0
            
            stats['timestamp'] = datetime.now().isoformat()
            
            return stats
        except Exception as e:
            logger.error(f"获取统计信息失败: {e}")
            return {}
    
    def test_camera_connection(self, camera_id: int) -> Dict[str, Any]:
        """测试摄像头连接"""
        try:
            camera = self.get_camera_by_id(camera_id)
            if not camera:
                return {
                    "success": False,
                    "message": "摄像头不存在"
                }
            
            if not camera.rtsp_url:
                return {
                    "success": False,
                    "message": "未配置RTSP地址"
                }
            
            # 这里应该实际测试RTSP连接
            # 为了简化，我们只做基本检查
            if camera.rtsp_url.startswith("rtsp://"):
                return {
                    "success": True,
                    "message": "连接测试通过",
                    "rtsp_url": camera.rtsp_url
                }
            else:
                return {
                    "success": False,
                    "message": "RTSP地址格式不正确"
                }
                
        except Exception as e:
            logger.error(f"测试摄像头连接失败: {e}")
            return {
                "success": False,
                "message": f"连接测试异常: {e}"
            }
    
    def sync_with_wvp(self, wvp_devices: List[Dict[str, Any]]) -> Dict[str, Any]:
        """与WVP设备同步"""
        try:
            sync_result = {
                "total_devices": len(wvp_devices),
                "created": 0,
                "updated": 0,
                "errors": []
            }
            
            for device in wvp_devices:
                try:
                    device_id = device.get("deviceId")
                    if not device_id:
                        continue
                    
                    # 查找现有摄像头
                    existing_camera = self.get_camera_by_wvp_device(device_id)
                    
                    camera_data = {
                        "name": device.get("name", f"WVP设备_{device_id}"),
                        "wvp_device_id": device_id,
                        "wvp_channel_id": device.get("channelId"),
                        "longitude": device.get("longitude", 0.0),
                        "latitude": device.get("latitude", 0.0),
                        "location": device.get("address"),
                        "status": "online" if device.get("online") else "offline"
                    }
                    
                    if existing_camera:
                        # 更新现有摄像头
                        self.update_camera(existing_camera.id, camera_data)
                        sync_result["updated"] += 1
                    else:
                        # 创建新摄像头
                        self.create_camera(camera_data)
                        sync_result["created"] += 1
                        
                except Exception as e:
                    sync_result["errors"].append(f"设备 {device.get('deviceId', 'unknown')}: {e}")
            
            logger.info(f"WVP同步完成: 创建={sync_result['created']}, 更新={sync_result['updated']}, 错误={len(sync_result['errors'])}")
            return sync_result
            
        except Exception as e:
            logger.error(f"WVP同步失败: {e}")
            return {
                "total_devices": 0,
                "created": 0,
                "updated": 0,
                "errors": [str(e)]
            }
    
    def save_ai_result(self, camera_id: int, algorithm: str, result_data: Dict[str, Any], 
                      confidence: float = None, processing_time: float = None) -> bool:
        """保存AI分析结果"""
        try:
            result_id = self.db.save_ai_result(camera_id, algorithm, result_data, confidence, processing_time)
            return result_id is not None
        except Exception as e:
            logger.error(f"保存AI结果失败: {e}")
            return False
    
    def get_ai_results(self, camera_id: int, algorithm: Optional[str] = None, 
                      limit: int = 100) -> List[Dict[str, Any]]:
        """获取AI分析结果"""
        try:
            return self.db.get_ai_results(camera_id, algorithm, limit)
        except Exception as e:
            logger.error(f"获取AI结果失败: {e}")
            return []
    
    def clear_cache(self):
        """清空缓存"""
        if self._cache_enabled:
            self._cache.clear()
            logger.info("摄像头服务缓存已清空")
    
    def cleanup(self):
        """清理资源"""
        self.clear_cache()
        logger.info("摄像头服务资源清理完成")


# 全局摄像头服务实例
_camera_service: Optional[CameraService] = None


def get_camera_service() -> CameraService:
    """获取摄像头服务实例"""
    global _camera_service
    if _camera_service is None:
        _camera_service = CameraService()
    return _camera_service